package com.example.commons.application;

import com.example.commons.launcher.LauncherService;
import com.example.commons.launcher.impl.NacosLauncherServiceImpl;
import lombok.NoArgsConstructor;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.env.*;
import org.springframework.util.StringUtils;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 自定义启动类
 * @author whx
 * @date 2022/4/12
 */
@EnableDiscoveryClient
@EnableAutoConfiguration
public class SpringSelfApplication {

    public static ConfigurableApplicationContext run(String applicationName, Class source, String... args){
        SpringApplicationBuilder builder = createBuilder(applicationName, source, args);
        return builder.run(args);
    }

    public static SpringApplicationBuilder createBuilder(String appName, Class source, String... args) {
        // 获取环境profile
        ConfigurableEnvironment environment = new StandardEnvironment();
        // 加载其他环境变量：如从命令行读取环境变量
        MutablePropertySources propertySources = environment.getPropertySources();
        propertySources.addFirst(new SimpleCommandLinePropertySource(args));
        propertySources.addLast(new MapPropertySource("systemProperties", environment.getSystemProperties()));
        propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", environment.getSystemEnvironment()));
        String[] activeProfiles = environment.getActiveProfiles();
        List<String> profiles = Arrays.asList(activeProfiles);
        List<String> activeProfileList = new ArrayList<>(profiles);
        Function<Object[], String> joinFun = StringUtils::arrayToCommaDelimitedString;
        SpringApplicationBuilder builder = new SpringApplicationBuilder(source);
        String profile;
        if (activeProfileList.isEmpty()) {
            profile = "dev";
            activeProfileList.add(profile);
            builder.profiles(profile);
        } else {
            if (activeProfileList.size() != 1) {
                throw new RuntimeException("同时存在环境变量:[" + StringUtils.arrayToCommaDelimitedString(activeProfiles) + "]");
            }
            profile = activeProfileList.get(0);
        }
        String activePros = joinFun.apply(activeProfileList.toArray());
        System.out.printf("----启动中，当前环境为:[%s]", activePros);
        Properties props = System.getProperties();
        // 加载通用配置项
        props.setProperty("spring.application.name", appName);
        props.setProperty("spring.profiles.active", profile);
        props.setProperty("file.encoding", StandardCharsets.UTF_8.name());
        Properties defaultProperties = new Properties();
        defaultProperties.setProperty("spring.main.allow-bean-definition-overriding", "true");
        builder.properties(defaultProperties);

        List<LauncherService> launcherList = new ArrayList<>();
        ServiceLoader.load(LauncherService.class).forEach(launcherList::add);

        (launcherList.stream().sorted(Comparator.comparing(LauncherService::getOrder)).collect(Collectors.toList())).forEach((launcherService) -> {
            launcherService.launcher(builder, appName, profile, isLocalDev());
        });

        return builder;


    }

    public static boolean isLocalDev() {
        String osName = System.getProperty("os.name");
        return StringUtils.hasText(osName) && !"LINUX".equalsIgnoreCase(osName);
    }

}
